package com.nl.logback;

import ch.qos.logback.classic.pattern.ClassicConverter;
import ch.qos.logback.classic.spi.ILoggingEvent;

import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;

/**
 * 日志显示IP
 *
 * @author breggor
 */
public class LocalIPConverter extends ClassicConverter {

    private static final Set<String> LOCAL_IPS = new CopyOnWriteArraySet<>();
    private static final String UNKNOWN_IP = "unknown";

    @Override
    public void start() {
        super.start();
        try {
            if (LOCAL_IPS.isEmpty()) {
                LOCAL_IPS.addAll(this.getLocalIps());
            }
        } catch (SocketException e) {
        }
    }

    @Override
    public void stop() {
        super.stop();
        LOCAL_IPS.clear();
    }

    @Override
    public String convert(ILoggingEvent iLoggingEvent) {
        if (!LOCAL_IPS.isEmpty()) {
            return LOCAL_IPS.stream().findFirst().get();
        }
        return UNKNOWN_IP;
    }

    /**
     * 获取所有网卡IP，排除回文地址、虚拟地址
     *
     * @return
     * @throws SocketException
     */
    private List<String> getLocalIps() throws SocketException {
        List<String> list = new ArrayList<>();
        Enumeration<NetworkInterface> enumeration = NetworkInterface.getNetworkInterfaces();
        while (enumeration.hasMoreElements()) {
            NetworkInterface intf = enumeration.nextElement();
            if (intf.isLoopback() || intf.isVirtual()) {
                continue;
            }
            Enumeration<InetAddress> inets = intf.getInetAddresses();
            while (inets.hasMoreElements()) {
                InetAddress addr = inets.nextElement();
                if (addr.isLoopbackAddress() || !addr.isSiteLocalAddress() || addr.isAnyLocalAddress()) {
                    continue;
                }
                list.add(addr.getHostAddress());
            }
        }
        return list;
    }
}

